#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

struct frame {
	char *func_name;
	unsigned valid : 1;
};

#define MAX_STACK_DEPTH 1024
struct frame stack[MAX_STACK_DEPTH] = {0};
unsigned stack_depth = 0;

FILE *of = NULL;
#define LOG_CHAIN_LEN 65536
char *watched = NULL;

__attribute__((constructor)) void init()
{
	of = stdout;
	watched = getenv("LOOKIN_FUNC");
}

void lookin_log_callchain()
{
	if (of == NULL)
		return;

	fprintf(of, "call chain: \n");
	for (int i=0;i<=stack_depth;++i) {
		fprintf(of, "%s\n", stack[i].func_name);
	}
	fprintf(of, "\n");
}

void lookin_enter(unsigned idx, char *name, char *ty_desc, char *arg_desc, ...)
{
	if (stack[stack_depth].valid == 1) {
		++stack_depth;
	}
	if (stack_depth == MAX_STACK_DEPTH) {
		return;
	}
	struct frame *fr = &stack[stack_depth];
	fr->func_name = name;
	fr->valid = 1;

	if (watched && strstr(name, watched)) {
		lookin_log_callchain();
	}
}

void lookin_exit(unsigned idx, char *name, char *ty_desc, char *arg_desc, ...)
{
	struct frame *fr = &stack[stack_depth];
	if (fr->valid && fr->func_name == name) {
		fr->func_name = NULL;
		fr->valid = 0;
		if (stack_depth != 0)
			--stack_depth;
	}
}

